package com.lancoo.ccas52.arrangecourse;

import com.lancoo.ccas52.arrangecourse.AlgDataSource.DataService.DataService;
import com.lancoo.ccas52.entity.*;
import com.lancoo.ccas52.pojo.dto.*;
import com.lancoo.ccas52.pojo.vo.Campus;
import com.lancoo.ccas52.pojo.vo.CollegeRoomVo;
import com.lancoo.ccas52.pojo.vo.WeekDateVo;
import com.lancoo.ccas52.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * @Description 算法
 * @Author Fortysun
 * @Date 2023/4/18 15:22
 **/
@Component
@Slf4j
public class ArrangeCourseDataSource {

    public static final boolean IS_MOCK_DATA = false;

    //课表排课计划
    @Resource
    @Lazy
    ScheduleService scheduleService;
    //排课基础规则
    @Resource
    BasicRuleService basicRuleService;
    //教室信息处理
    @Resource
    RoomService roomService;
    //学期开课计划服务
    @Resource
    @Lazy
    TaskInfoService taskInfoService;

    //冲突处理服务
    @Resource
    ScheduleConflictInfoService conflicService;

    //测试数据生成项目，产生的测试数据服务
    @Resource
    DataService dataService;

    /**
     * 获取教学班信息列表
     * @param taskId 学期计划id
     * @param campusId 校区id， null全部
     * @param collegeId 院系id，教务管理员登录传null
     * @param majorProp 课程类型，1：公共课， 2：专业课
     * @return
     */
    public List<ArrangeTeachingClassDto> getTeachingClassList(Integer taskId, String campusId,String collegeId,Integer majorProp) {
        if (IS_MOCK_DATA) {
            return dataService.getTeachingClassList(campusId);
        }
        //实际数据
        List<ArrangeTeachingClassDto> teachingClassList = scheduleService.getTeachingClassDate(taskId, campusId,collegeId,majorProp);
        if (teachingClassList == null || teachingClassList.isEmpty()) {
            log.error("ArrangeCourseDataSource--getTeachingClassList: 排课教学班数据，获取失败~！！");
            return new ArrayList<>();
        }
        return teachingClassList;
    }

    /**
     * 获取教室数据
     * @param schoolId 学校id
     * @param termId 学期id
     * @param campusId null全部
     * @return
     */
    public List<ArrangeRoomDto> getRoomList(String schoolId, String termId, String campusId) {
        if (IS_MOCK_DATA) {
            return dataService.getRoomList(campusId);
        }
        //实际数据
        List<ArrangeRoomDto> roomList = scheduleService.getArrangeRoom(schoolId,termId, campusId);
        if (roomList == null || roomList.isEmpty()) {
            log.error("ArrangeCourseDataSource--getRoomList: 排课教学班数据，获取失败~！！");
            return new ArrayList<>();
        }
        return roomList;
    }

    /**
     * 获取学时信息 （过滤掉时间禁排的学时）
     * @param schoolId 学校id
     * @param termId 学期id
     * @param collegeId 院系id，教务管理员登录传null
     * @return
     */
    public List<ArrangePeriod> getTimeslotList(String schoolId, String termId, String collegeId) {
        if (IS_MOCK_DATA) {
            return dataService.getTimeslotList();
        }
        //实际数据
        List<ArrangePeriod> timeslotList =  scheduleService.getArrangeTimeCode(schoolId,termId,collegeId);
        if (timeslotList == null || timeslotList.isEmpty()) {
            log.error("ArrangeCourseDataSource--getTimeslotList: 排课课时数据，获取失败~！！");
            return new ArrayList<>();
        }
        return timeslotList;
    }

    /**
     * 场地禁排的信息
     * @param schoolId 学校id
     * @param termId 学期id
     * @param campusId null全部
     * @param collegeId 院系id，教务管理员登录传null
     * @return
     */
    public List<ArrangeRoomRuleDto> getRoomRuleList(String schoolId, String termId, String campusId, String collegeId) {
        if (IS_MOCK_DATA) {
            return dataService.getRoomRuleList(campusId);
        }
        //实际数据
        List<ArrangeRoomRuleDto> roomRuleList = scheduleService.getArrangeRoomProhibit(schoolId,termId,campusId,collegeId);
        if (roomRuleList == null || roomRuleList.isEmpty()) {
            log.info("ArrangeCourseDataSource--getRoomRuleList: 排课教室禁排规则数据，获取失败~！！");
            return new ArrayList<>();
        }
        return roomRuleList;
    }

    /**
     * 获取教师禁排部分字段
     * @param schoolId 学校id
     * @param termId 学期id
     * @param collegeId 院系id，教务管理员登录传null
     * @return
     */
    public List<ArrangeTeacherRuleDto> getTeacherRuleList(String schoolId, String termId, String collegeId) {
        if (IS_MOCK_DATA) {
            return dataService.getTeacherRuleList();
        }
        //实际数据
        List<ArrangeTeacherRuleDto> teacherRuleList = scheduleService.getArrangeTeacherTime(schoolId,termId,collegeId);
        if (teacherRuleList == null || teacherRuleList.isEmpty()) {
            log.info("ArrangeCourseDataSource--getTeacherRuleList: 排课教师规则数据数据，获取失败~！！");
            return new ArrayList<>();
        }
        return teacherRuleList;
    }

    /**
     * 获取课程禁排部分字段
     * @param taskId 学期计划id
     * @return
     */
    public List<ArrangeCourseRuleDto> getCourseRuleList(Integer taskId) {
        if (IS_MOCK_DATA) {
            return dataService.getCourseRuleList();
        }
        //实际数据
        List<ArrangeCourseRuleDto> courseRuleList = scheduleService.getArrangeCourseProhibit(taskId);
        if (courseRuleList == null || courseRuleList.isEmpty()) {
            log.info("ArrangeCourseDataSource--getCourseRuleList: 排课课程规则数据，获取失败~！！");
            return new ArrayList<>();
        }
        return courseRuleList;
    }

    /**
     * 获取已经锁定的课表  包含教学班的教室id、学时信息
     * @param taskId 学期计划id
     * @param campusId campusId null全部
     * @param isLocked 1未锁定  2锁定 null全部
     * @param majorProp  用于区分排课类型 传null表示仅教务管理员排课，获取锁定课表
     * @return
     */
    public List<ArrangeScheduleDto> getLockedScheduleList(Integer taskId, String campusId, Integer isLocked, Integer majorProp, String collegeId) {
        if (IS_MOCK_DATA) {
            return null;
        }
        //实际数据
        List<ArrangeScheduleDto> scheduleLockedList =  scheduleService.getLockSchedule(taskId,campusId, isLocked, majorProp,collegeId);
        if (scheduleLockedList == null || scheduleLockedList.isEmpty()) {
            log.info("ArrangeCourseDataSource--getLockedScheduleList: 排课已锁定的课表数据，获取失败~！！");
            return new ArrayList<>();
        }
        return scheduleLockedList;
    }

    /**
     * 存储每轮排课的课程信息，即课表信息
     * @param taskId 学期计划id
     * @param schedules 课表列表信息
     */
    public void addBathSchedule(Integer taskId,List<Schedule> schedules,String collegeId,Integer majorProp) {
        try {
            scheduleService.addBathSchedule(taskId, schedules,collegeId,majorProp);
        } catch (Exception ex) {
            log.error("ArrangeCourseDataSource--addBathSchedule: 插入课表数据失败，原因："+ex.getMessage());
        }

    }
    /**
     * 存储每轮排课的冲突信息
     * @param taskId 学期计划id
     * @param scheduleConflicts 冲突的课表列表信息
     */
    public void addBatchScheduleConflict(Integer taskId,List<ScheduleConflictInfo> scheduleConflicts) {
        try {
            scheduleService.addBatchScheduleConflict(taskId, scheduleConflicts,null);
        }catch (Exception ex) {
            log.error("ArrangeCourseDataSource--addBatchScheduleConflict: 插入冲突信息数据失败，原因："+ex.getMessage());
        }

    }

    /**
     * 存储每轮排课的冲突信息
     * @param updateList 需要更新冲突状态的教学班列表信息
     */
    public void updateScheduleState(List<ArrangeTeachingClassUpdate> updateList) {
        try {
            scheduleService.updateScheduleState(updateList);
        }catch (Exception ex) {
            log.error("ArrangeCourseDataSource--updateScheduleState: 更新教学班冲突状态信息失败，原因："+ex.getMessage());
        }

    }

    /**
     * 获取校区信息
     * @param taskId 学期计划id
     * @return
     */
    public List<Campus> getCampusList(Integer taskId) {
        if (IS_MOCK_DATA) {
            return dataService.getCampusList();
        }
        //实际数据
        List<Campus> campusList = roomService.getCampusList(taskId);
        if (campusList == null || campusList.isEmpty()) {
            log.error("ArrangeCourseDataSource--getCampusList: 排课校区列表数据，获取失败~！！");
            return new ArrayList<>();
        }

        return campusList;
    }

    /**
     * 获取基础规则
     * @param schoolId 学校id
     * @param termId 学期id
     * @param taskId 学期计划id
     * @param collegeId 院系id，教务管理员登录传null
     * @return
     */
    public List<RuleUsable> getBaseRuleList(String schoolId, String termId, Integer taskId, String collegeId) {
        if (IS_MOCK_DATA) {
            return dataService.getBaseRuleList();
        }
        //实际数据
        List<RuleUsable> baseRuleList =  basicRuleService.getCurrent(taskId,schoolId,termId,collegeId);
        if (baseRuleList == null || baseRuleList.isEmpty()) {
            log.error("ArrangeCourseDataSource--getBaseRuleList: 排课基础规则数据，获取失败~！！");
            return new ArrayList<>();
        }
        return baseRuleList;
    }

    /**
     * 获取高级规则设置的教师规则信息
     * @param taskId 排课选课计划id
     * @param collegeId 院系id，教务管理员登录传null
     * @return
     */
    public RuleTeacherSetting getTeacherSetting(Integer taskId, String collegeId) {
        if (IS_MOCK_DATA) {
            return dataService.getTeacherSetting(taskId);
        }
        RuleTeacherSetting teacherSetting = basicRuleService.getTeacherSetting(taskId,collegeId);
        if (teacherSetting == null) {
            log.error("ArrangeCourseDataSource--getTeacherSetting: 高级规则设置的教师规则信息获取失败~！！");
            return null;
        }

        return teacherSetting;
    }

    /**
     * 获取学期总周数
     * @param taskId
     * @return
     */
    public WeekDateVo getTermWeeks(Integer taskId) {
        if (IS_MOCK_DATA) {
            return dataService.getTermWeeks(taskId);
        }
        WeekDateVo weekDate = taskInfoService.countWeek(taskId);
        if (weekDate == null) {
            log.error("ArrangeCourseDataSource--getTermWeeks: 排课教学班数据获取失败~！！");
            return null;
        }
        return weekDate;
    }

    /**
     * 获取排课选课的计划信息
     * @param taskId 计划id
     * @return
     */
    public TaskInfo getTaskInfo(Integer taskId) {
        if (IS_MOCK_DATA) {
            return dataService.getTaskInfo(taskId);
        }
        TaskInfo taskInfo = taskInfoService.getById(taskId);
        if (taskInfo == null) {
            log.error("ArrangeCourseDataSource--getTaskInfo: 排课学期排课选课计划信息获取失败~！！");
            return null;
        }
        return taskInfo;
    }

    /**
     * 获取指定教学班的冲突信息
     * @param teachingClassId 教学班id
     * @return
     */
    public List<ScheduleConflictInfo> getTeachingClassConflictList(Long teachingClassId) {
        List<ScheduleConflictInfo> conflictList =  conflicService.lambdaQuery()
                .eq(ScheduleConflictInfo::getTeachingClassId, teachingClassId)
                .or()
                .eq(ScheduleConflictInfo::getClashTeachingClassId, teachingClassId)
                .list();

        if (conflictList == null || conflictList.isEmpty()) {
            log.error("ArrangeCourseDataSource--getTeachingClassConflictList: 指定教学班的冲突信息，获取失败~！！");
            return new ArrayList<>();
        }
        return  conflictList;
    }

    /**
     * 批量更新冲突列表信息
     * @param conflictList 待更新的冲突信息列表
     */
    public void updateAndAddConflictList(List<ScheduleConflictInfo> conflictList) {
        try {
            conflicService.saveOrUpdateBatch(conflictList);
        }catch (Exception ex) {
            log.error("ArrangeCourseDataSource--updateConflictList: 更新冲突列表信息失败，原因："+ex.getMessage());
        }
    }

    /**
     * 批量删除冲突信息
     * @param conflictList 待删除的冲突信息列表
     */
    public void removeConflictList(List<ScheduleConflictInfo> conflictList) {
        try {
            conflicService.removeBatchByIds(conflictList);
        }catch (Exception ex) {
            log.error("ArrangeCourseDataSource--removeConflictList: 删除冲突列表信息失败，原因："+ex.getMessage());
        }
    }

    /**
     * 获取学校，指定学期的学期排课计划信息列表
     * @param schoolId 学校id
     * @param termId 学期id
     * @return
     */
    public List<TaskInfo> getTaskList(String schoolId, String termId) {
        List<TaskInfo> taskList = taskInfoService.lambdaQuery()
                .eq(TaskInfo::getSchoolId,schoolId)
                .eq(TaskInfo::getTerm, termId)
                .list();
        if (taskList == null || taskList.isEmpty()) {
            log.error("ArrangeCourseDataSource--getTaskList: 学期的计划列表获取失败，获取失败~！！");
            return new ArrayList<>();
        }
        return taskList;
    }

    /**
     * 获取排课的院系的上课场地范围
     * @param taskId 计划id
     * @param collegeId 院系id，教务管理员登录传null
     * @return
     */
    public List<CollegeRoomVo> getCollegeRoomList(Integer taskId, String collegeId) {
        List<CollegeRoomVo> collegeRoomList = basicRuleService.getCollegeRoom(taskId, collegeId, null);
        if (collegeRoomList == null || collegeRoomList.isEmpty()) {
            log.error("ArrangeCourseDataSource--getCollegeRoomList: 院系场地范围列表获取失败，获取失败~！！");
            return new ArrayList<>();
        }
        return collegeRoomList;
    }
}
